# @File ：base.py
# -*- encoding: utf-8 -*-
# @Time: 2021/10/3 22:19
# @Author: niu run peng
import json
import os
from urllib.parse import unquote

import requests
import yaml
from jinja2 import Template
from utils.tools import CommonTools
from jsonschema import validate

obj_path = os.path.abspath(__file__).split('RequestObj')[0] + 'RequestObj/'


class APIBase:
    sender = requests.Session()
    tools = CommonTools()
    extracts = {}

    def __init__(self, protocol, host):
        self.area = f'{protocol}://{host}/'

    def send_request(self, desc, method: str, route, data=None, json_=None, params=None, headers=None,
                     proxies=None):
        method = method.upper()
        if method == 'GET':
            return self.send_get(desc, route, params=params, headers=headers, proxies=proxies)
        elif method == 'POST':
            return self.send_post(desc, route, data=data, json_=json_, params=params, headers=headers, proxies=proxies)
        else:
            ...

    def send_get(self, desc, route, params=None, headers=None, proxies=None):
        resp = self.sender.get(url=self.area + route, params=params, headers=headers, verify=False, proxies=proxies)
        self.console_print(desc, resp)
        return self.auto_type(resp)

    def send_post(self, desc, route, data=None, json_=None, params=None, headers=None, proxies=None):
        resp = self.sender.post(url=self.area + route, data=data, json=json_, params=params, headers=headers,
                                verify=False, proxies=proxies)
        self.console_print(desc, resp)
        return self.auto_type(resp)

    @staticmethod
    def console_print(description, resp: requests.Response):
        print('\n', '++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++')
        print('Description: ', description)
        print('Headers:', resp.request.headers)
        print(resp.request.method, ' ', unquote(resp.request.url))
        if resp.request.method != 'GET':
            print('ReqBody:', '\n', str(resp.request.body, 'utf-8').encode('utf-8').decode('unicode_escape'))
        print('RespBody:', '\n', resp.text)
        print('RespType:', resp.headers['content-type'])
        print('RespTime:', resp.elapsed.microseconds / 1000, 'ms')
        print('---------------------------------------------------------------------------------')

    @staticmethod
    def auto_type(resp: requests.Response):
        if 'content-type' in resp.headers.keys():
            content_type = resp.headers['content-type']
            if 'json' in content_type:
                return resp.json()
            if 'text' in content_type or 'html' in content_type:
                return resp.text
            if 'xml' in content_type:
                ...
        else:
            return resp

    @classmethod
    def json_temp_complete(cls, temp_file: str, params: dict = None, by_extracts=False) -> json:
        """使用jinja2模板引擎补全json"""
        path = temp_file.split('../')[1]
        with open(os.path.join(obj_path, path), encoding='utf-8') as f:
            source = f.read().replace('\n', '').replace('  ', '')
        temp = Template(source, trim_blocks=True)
        if params and by_extracts is False:
            result = temp.render(params)
        elif by_extracts and params is None:
            result = temp.render(cls.extracts)
        elif params and by_extracts:
            extracts_copy = cls.extracts.copy()
            extracts_copy.update(params)
            result = temp.render(extracts_copy)
        else:
            result = temp.render()
        return json.loads(result)

    def update_extracts(self, resp, extract: dict):
        """接口需要提取的参数保存到base类中,其他依赖该base类实例的接口可使用补全模板以实现参数传递"""
        if extract:
            for k, v in extract.items():
                value = self.tools.json_path(resp, v)
                extract[k] = value
            APIBase.extracts.update(extract)

    def json_schema(self, resp, file='', params: dict = None, by_extracts=False):
        """检查json详细数据类型等"""
        if file:
            if params:
                if 'schema' in params:
                    schema = self.json_temp_complete(file, params['schema'], by_extracts)
                else:
                    schema = self.json_temp_complete(file)
            else:
                schema = self.json_temp_complete(file)
            print('schema:', schema)
            validate(resp, schema)

    @staticmethod
    def find_file(name):
        """项目下文件名获取文件路径"""
        for rel_path, dirs, files in os.walk(obj_path):
            if name in files:
                full_path = os.path.join(obj_path, rel_path, name)
                return os.path.normpath(os.path.abspath(full_path))
